package com.zmn.brs.business.impl.objective;

import com.alibaba.fastjson.JSONObject;
import com.zmn.brs.business.interfaces.objective.ObjectivePrincipalBService;
import com.zmn.brs.business.interfaces.rule.AlarmRuleBService;
import com.zmn.brs.common.enums.EventTypeEnum;
import com.zmn.brs.common.enums.ThresholdExpressionEnum;
import com.zmn.brs.dto.PrincipalEditDTO;
import com.zmn.brs.dto.PrincipalDelDTO;
import com.zmn.brs.dubbo.constant.DubboConsts;
import com.zmn.brs.model.entity.event.Event;
import com.zmn.brs.model.entity.event.EventQuery;
import com.zmn.brs.model.entity.threshold.Threshold;
import com.zmn.brs.model.entity.threshold.ThresholdQuery;
import com.zmn.brs.model.vo.rule.objective.ObjectiveRuleVO;
import com.zmn.brs.services.interfaces.event.EventService;
import com.zmn.brs.services.interfaces.threshold.ThresholdService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.okr.common.constant.ObjectiveMasterTypeConst;
import com.zmn.okr.common.model.dio.objective.ObjectiveDIO;
import com.zmn.okr.dubbo.interfaces.objective.ObjectiveRemoteService;
import com.zmn.plat.common.dictionary.StatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * 描述：OKR 目标责任人实现
 *
 * @author chongw
 * @since 2021-07-20 14:23
 */
@Slf4j
@Service
public class ObjectivePrincipalBServiceImpl implements ObjectivePrincipalBService {

    public static final String TAG = "OKR目标责任人同步服务实现";

    @Resource
    EventService eventService;

    @Resource
    AlarmRuleBService alarmRuleBService;

    @Resource
    ThresholdService thresholdService;

    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    ObjectiveRemoteService objectiveRemoteService;

    /**
     * 新增责任人规则
     * @param principalEditDTO
     */
    @Override
    public void edit(PrincipalEditDTO principalEditDTO){
        try {
            Date now = DateUtil.getNow();
            if (principalEditDTO == null) {
                log.error("[{}], 新增消息体为空！", TAG);
                return;
            }
            //判断是否责任人
            if (!ObjectiveMasterTypeConst.MASTERTYPE_PERSON.equals(principalEditDTO.getObjMasterType())) {
                log.error("[{}], 当前对象类型不是责任人数据！", TAG);
                return;
            }
            //获取okr子目标信息
            ResponseDTO<ObjectiveDIO> objectiveDIOResponseDTO = objectiveRemoteService.getObjective(principalEditDTO.getSubgoalId());
            if(!objectiveDIOResponseDTO.isSuccess() || objectiveDIOResponseDTO.getData() == null){
                log.error("[{}], 查询责任人目标，目标ID：{}, 查询内容为空或者错误！！！，响应内容：{}", TAG,
                        principalEditDTO.getSubgoalId(),
                        JSONObject.toJSONString(objectiveDIOResponseDTO));
                return;
            }
            //查询责任人目标
            ObjectiveDIO objectiveDIO = Optional.ofNullable(objectiveDIOResponseDTO.getData()).orElse(new ObjectiveDIO());
            log.info("[{}], 查询责任人目标，目标ID：{}, okr获取目标详情接口响应：{}", TAG, principalEditDTO.getSubgoalId(), JSONObject.toJSONString(objectiveDIO));
            //判断生效时间是否在当前时间之后，则删除对应规则
            if(objectiveDIO.getValidTime().after(now)){
                log.error("[{}], 目标ID：{}， 执行删除规则阈值，当前目标未生效！！！", TAG, principalEditDTO.getSubgoalId());
                this.del(PrincipalDelDTO.builder()
                        .staffIds(Arrays.asList(objectiveDIO.getObjMaster()))
                        .objMasterType(objectiveDIO.getObjMasterType())
                        .parentObjId(objectiveDIO.getParentObjId())
                        .creater(principalEditDTO.getCreater())
                        .createTime(principalEditDTO.getCreateTime())
                        .build());
                return;
            }
            EventQuery eventQuery = new EventQuery();
            eventQuery.setRelateId(principalEditDTO.getParentObjId());
            eventQuery.setEventType(EventTypeEnum.OBJECTIVE.getTypeId());
            List<Event> eventList = eventService.listByQuery(eventQuery);
            if (eventList == null || (eventList != null && eventList.size() == 0)) {
                log.error("[{}], 部门目标ID：{}， 当前目标未找到对应事件！", TAG, principalEditDTO.getParentObjId());
                return;
            }
            //获取目标事件
            Event event = eventList.get(0);
            //获取事件对应规则
            Integer ruleId = alarmRuleBService.findRuleIdByEventId(event.getEventId());
            if (NumberUtil.isNullOrZero(ruleId)) {
                log.error("[{}], 部门目标ID：{}， 事件ID:{}， 当前事件未找到对应规则！", TAG, principalEditDTO.getParentObjId(), event.getEventId());
                return;
            }
            ThresholdQuery thresholdQuery = ThresholdQuery.builder()
                    .ruleId(ruleId)
                    .build();
            List<Threshold> thresholdList = thresholdService.listByQuery(thresholdQuery);
            //查询责任是否存在当前规则下
            List<Threshold> tempList = thresholdList.stream().filter(o -> {
                ObjectiveRuleVO vo = JSONObject.parseObject(o.getThresholdValue(), ObjectiveRuleVO.class);
                return principalEditDTO.getStaffId().equals(vo.getObjMaster());
            }).collect(Collectors.toList());
            AtomicReference<Integer> flag = new AtomicReference<>(0);
            //设置目标，修改阈值
            if(!tempList.isEmpty() && tempList.size() > 0){
                tempList.forEach(threshold -> {
                    //获取当前责任人阈值
                    ObjectiveRuleVO vo = JSONObject.parseObject(threshold.getThresholdValue(), ObjectiveRuleVO.class);
                    vo.setSubgoalId(principalEditDTO.getSubgoalId());
                    threshold.setThresholdValue(JSONObject.toJSONString(vo));
                    threshold.setUpdater(principalEditDTO.getCreater());
                    threshold.setUpdateTime(now);
                    flag.updateAndGet(v -> v + thresholdService.updateByKey(threshold));
                    if (flag.get() > 0) {
                        log.info("[{}], 阈值ID:{} , 责任人更新目标ID同步成功！！！", TAG, threshold.getThresholdId());
                        return;
                    }
                });
            }
            //新增责任人，添加阈值
            else{
                ObjectiveRuleVO objectiveRuleVO = ObjectiveRuleVO.builder()
                        .objMasterType(objectiveDIO.getObjMasterType())
                        .objMaster(objectiveDIO.getObjMaster())
                        .objMasterName(objectiveDIO.getObjMasterName())
                        .deptId(objectiveDIO.getDeptId())
                        .deptName(objectiveDIO.getDeptName())
                        .subgoalId(objectiveDIO.getSubgoalId())
                        .list(eventService.getDefatultEarlyWarningConfig())
                        .build();
                //插入责任人值域
                Threshold threshold = Threshold.builder()
                        .ruleId(ruleId)
                        .thresholdName(String.format("[%s]绩效经营指标预警值", objectiveDIO.getObjMasterName()))
                        .type(0)
                        .thresholdParam(String.valueOf(objectiveDIO.getParentObjId()))
                        .expression(ThresholdExpressionEnum.ALL.getExpression())
                        .thresholdValue(JSONObject.toJSONString(objectiveRuleVO))
                        .status(StatusEnum.ENABLE.getCode())
                        .creater(principalEditDTO.getCreater())
                        .updater(principalEditDTO.getCreater())
                        .createTime(now)
                        .updateTime(now)
                        .build();
                flag.updateAndGet(v -> v + thresholdService.insert(threshold));
                if (flag.get() > 0) {
                    log.info("[{}], 阈值ID:{} , 新增责任人同步成功！！！", TAG, threshold.getThresholdId());
                    return;
                }
            }
            log.error("[{}], 责任人同步失败！！！", TAG);
        }catch (Exception e){
            log.error("[{}], 责任人同步异常！！！，异常信息：{}", TAG , e);
        }
    }

    /**
     * 删除责任人规则
     * @param principalDelDTO
     */
    @Override
    @Transactional
    public void del(PrincipalDelDTO principalDelDTO){
        try {
            if (principalDelDTO == null) {
                log.error("[{}], 删除消息体为空！", TAG);
                return;
            }
            //判断是否责任人
            if (!ObjectiveMasterTypeConst.MASTERTYPE_PERSON.equals(principalDelDTO.getObjMasterType())) {
                return;
            }
            //获取删除责任ID
            List<Integer> staffIds = principalDelDTO.getStaffIds();
            if (staffIds == null) {
                log.error("[{}], 目标ID：{}，OKR删除责任人为空！！！", TAG, principalDelDTO.getParentObjId());
                return;
            }
            EventQuery eventQuery = new EventQuery();
            eventQuery.setRelateId(principalDelDTO.getParentObjId());
            eventQuery.setEventType(EventTypeEnum.OBJECTIVE.getTypeId());
            List<Event> eventList = eventService.listByQuery(eventQuery);
            if (eventList == null || (eventList != null && eventList.size() == 0)) {
                log.error("[{}], 目标ID：{}， 当前目标未找到对应事件！", TAG, principalDelDTO.getParentObjId());
                return;
            }
            //获取目标事件
            Event event = eventList.get(0);
            //获取事件对应规则
            Integer ruleId = alarmRuleBService.findRuleIdByEventId(event.getEventId());
            if (NumberUtil.isNullOrZero(ruleId)) {
                log.error("[{}], 目标ID：{}， 事件ID:{}， 当前事件未找到对应规则！", TAG, principalDelDTO.getParentObjId(), event.getEventId());
                return;
            }
            AtomicReference<Integer> flag = new AtomicReference<>(0);
            //删除责任人
            staffIds.forEach(o -> {
                ThresholdQuery thresholdQuery = ThresholdQuery.builder()
                        .ruleId(ruleId)
                        .build();
                List<Threshold> thresholdList = thresholdService.listByQuery(thresholdQuery);
                thresholdList.stream().filter(f ->{
                    ObjectiveRuleVO vo = JSONObject.parseObject(f.getThresholdValue(), ObjectiveRuleVO.class);
                    return o.equals(vo.getObjMaster());
                }).forEach(j -> {
                    flag.updateAndGet(v -> v + thresholdService.deleteByKey(j.getThresholdId()));
                });
            });
            if(flag.get() > 0){
                log.info("[{}], 删除责任人同步成功！！！，删除数量：{}", TAG, flag.get());
                return;
            }
            log.error("[{}], 删除责任人同步失败！！！", TAG);
        }catch (Exception e){
            log.error("[{}], 删除责任人同步异常！！！，异常信息：{}", TAG , e);
        }
    }

}
